package concurrent;

import java.util.concurrent.*;

/**
 * 死锁
 * @author jack.wu
 * @since 2019/12/25 14:12
 */
public class DeadlockDemo {

    public static void main(String[] args) {
        Obj1 obj1 = new Obj1();
        Obj2 obj2 = new Obj2();
        Thread t1 = new Thread(new SynAddRunnable(obj1, obj2, 1, 2, false));
        t1.setName("Thread1 - ");
        t1.start();
        Thread t2 = new Thread(new SynAddRunnable(obj1, obj2, 1, 2, true));
        t2.setName("Thread2 - ");
        t2.start();
    }

    static class Obj1 {

    }

    static class Obj2 {

    }

    static class SynAddRunnable implements Runnable {
        private Obj1 obj1;
        private Obj2 obj2;
        int a, b;
        boolean flag;

        public SynAddRunnable(Obj1 obj1, Obj2 obj2, int a, int b, boolean flag) {
            this.obj1 = obj1;
            this.obj2 = obj2;
            this.a = a;
            this.b = b;
            this.flag = flag;
        }

        @Override
        public void run() {
            try {
                if (flag) {
                    synchronized (obj1) {
                        Thread.sleep(100);
                        synchronized (obj2) {
                            System.out.println(a + b);
                        }
                    }
                } else {
                    synchronized (obj2) {
                        Thread.sleep(100);
                        synchronized (obj1) {
                            System.out.println(a + b);
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 饥饿，是指某一个或者多个线程因为种种原因无法获得所要的资源，导致一直无法执行。
 * 比如它的优先级可能太低，而高优先级的线程不断抢占它需要的资源，导致低优先级线程无法工作。
 */
class HungerLock {
    private static ExecutorService service = Executors.newSingleThreadExecutor();

    public static class AnotherCallable implements Callable {

        @Override
        public Object call() throws Exception {
            System.out.println("in AnotherCallable");
            return "another success";
        }
    }

    public static class MyCallable implements Callable {

        @Override
        public Object call() throws Exception {
            System.out.println("in MyCallable");
            Future future = service.submit(new AnotherCallable());
            return "success" + future.get();
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        Future future = service.submit(myCallable);
        System.out.println(future.get());
        service.shutdown();
    }
}
